import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import rcParams
import io
import base64
from flask import Flask, render_template

app = Flask(__name__)

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

# 加载数据
df = pd.read_csv('electric_vehicle_analytics.csv')


@app.route('/')
def index():
    # 生成所有图表
    plots = {
        'brand_distribution': plot_brand_distribution(),
        'region_distribution': plot_region_distribution(),
        'battery_vs_range': plot_battery_vs_range(),
        'vehicle_type_distribution': plot_vehicle_type_distribution(),
        'charging_time_distribution': plot_charging_time_distribution(),
        'battery_health_distribution': plot_battery_health_distribution(),
        'speed_vs_energy_consumption': plot_speed_vs_energy_consumption(),
        'summary_stats': get_summary_stats()
    }
    return render_template('index.html', plots=plots)


def plot_to_base64(plt):
    """将matplotlib图表转换为base64编码的图片"""
    img = io.BytesIO()
    plt.savefig(img, format='png', bbox_inches='tight', dpi=100)
    img.seek(0)
    plt.close()
    return base64.b64encode(img.getvalue()).decode()


def get_summary_stats():
    """获取数据集的统计摘要"""
    stats = {
        'total_vehicles': len(df),
        'unique_brands': df['Make'].nunique(),
        'unique_models': df['Model'].nunique(),
        'years_range': f"{df['Year'].min()} - {df['Year'].max()}",
        'avg_battery_capacity': round(df['Battery_Capacity_kWh'].mean(), 2),
        'avg_range': round(df['Range_km'].mean(), 2),
        'avg_battery_health': round(df['Battery_Health_%'].mean(), 2)
    }
    return stats


def plot_brand_distribution():
    """各品牌车辆数量分布"""
    plt.figure(figsize=(12, 8))

    # 使用pandas进行品牌计数
    brand_counts = df['Make'].value_counts()

    # 计算百分比
    brand_percentages = (brand_counts / len(df) * 100).round(1)

    # 创建柱状图
    bars = plt.bar(brand_counts.index, brand_counts.values,
                   color=plt.cm.Set3(np.arange(len(brand_counts))))

    # 添加数值标签
    for i, (count, percentage) in enumerate(zip(brand_counts.values, brand_percentages.values)):
        plt.text(i, count + 5, f'{count}\n({percentage}%)',
                 ha='center', va='bottom', fontsize=9)

    plt.title('各品牌车辆数量分布', fontsize=16, fontweight='bold')
    plt.xlabel('汽车品牌', fontsize=12)
    plt.ylabel('车辆数量', fontsize=12)
    plt.xticks(rotation=45, ha='right')
    plt.grid(axis='y', alpha=0.3)

    return plot_to_base64(plt)


def plot_region_distribution():
    """各地区车辆分布"""
    plt.figure(figsize=(10, 10))

    # 使用pandas进行地区计数
    region_counts = df['Region'].value_counts()

    # 创建饼图
    colors = plt.cm.Pastel1(np.arange(len(region_counts)))
    wedges, texts, autotexts = plt.pie(region_counts.values,
                                       labels=region_counts.index,
                                       autopct='%1.1f%%',
                                       colors=colors,
                                       startangle=90)

    # 美化文本
    for autotext in autotexts:
        autotext.set_color('white')
        autotext.set_fontweight('bold')
        autotext.set_fontsize(10)

    plt.title('各地区车辆分布', fontsize=16, fontweight='bold')
    plt.axis('equal')

    return plot_to_base64(plt)


def plot_battery_vs_range():
    """电池容量与续航关系"""
    plt.figure(figsize=(12, 8))

    # 使用numpy计算相关系数
    correlation = np.corrcoef(df['Battery_Capacity_kWh'], df['Range_km'])[0, 1]

    # 创建散点图
    scatter = plt.scatter(df['Battery_Capacity_kWh'], df['Range_km'],
                          c=df['Battery_Health_%'], cmap='viridis',
                          alpha=0.7, s=50)

    # 添加颜色条
    plt.colorbar(scatter, label='电池健康度 (%)')

    # 添加趋势线
    z = np.polyfit(df['Battery_Capacity_kWh'], df['Range_km'], 1)
    p = np.poly1d(z)
    plt.plot(df['Battery_Capacity_kWh'], p(df['Battery_Capacity_kWh']),
             "r--", alpha=0.8, linewidth=2)

    plt.title(f'电池容量与续航关系 (相关系数: {correlation:.3f})', fontsize=16, fontweight='bold')
    plt.xlabel('电池容量 (kWh)', fontsize=12)
    plt.ylabel('续航里程 (km)', fontsize=12)
    plt.grid(alpha=0.3)

    return plot_to_base64(plt)


def plot_vehicle_type_distribution():
    """车辆类型分布"""
    plt.figure(figsize=(12, 8))

    # 使用pandas进行车辆类型计数
    vehicle_type_counts = df['Vehicle_Type'].value_counts()

    # 创建水平柱状图
    bars = plt.barh(vehicle_type_counts.index, vehicle_type_counts.values,
                    color=plt.cm.Set2(np.arange(len(vehicle_type_counts))))

    # 添加数值标签
    for i, (value, category) in enumerate(zip(vehicle_type_counts.values, vehicle_type_counts.index)):
        plt.text(value + 5, i, f'{value}', va='center', fontsize=11, fontweight='bold')

    plt.title('车辆类型分布', fontsize=16, fontweight='bold')
    plt.xlabel('车辆数量', fontsize=12)
    plt.ylabel('车辆类型', fontsize=12)
    plt.grid(axis='x', alpha=0.3)

    return plot_to_base64(plt)


def plot_charging_time_distribution():
    """充电时间分布"""
    plt.figure(figsize=(12, 8))

    # 使用numpy计算统计量
    mean_charge_time = np.mean(df['Charging_Time_hr'])
    median_charge_time = np.median(df['Charging_Time_hr'])

    # 创建直方图
    n, bins, patches = plt.hist(df['Charging_Time_hr'], bins=30,
                                color='skyblue', edgecolor='black', alpha=0.7)

    # 添加均值和中位数线
    plt.axvline(mean_charge_time, color='red', linestyle='--', linewidth=2,
                label=f'均值: {mean_charge_time:.2f}小时')
    plt.axvline(median_charge_time, color='green', linestyle='--', linewidth=2,
                label=f'中位数: {median_charge_time:.2f}小时')

    plt.title('充电时间分布', fontsize=16, fontweight='bold')
    plt.xlabel('充电时间 (小时)', fontsize=12)
    plt.ylabel('频率', fontsize=12)
    plt.legend()
    plt.grid(alpha=0.3)

    return plot_to_base64(plt)


def plot_battery_health_distribution():
    """电池健康度分布"""
    plt.figure(figsize=(14, 8))

    # 创建子图
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

    # 左图：整体分布直方图
    n, bins, patches = ax1.hist(df['Battery_Health_%'], bins=20,
                                color='lightgreen', edgecolor='black', alpha=0.7)
    ax1.set_title('电池健康度整体分布', fontsize=14, fontweight='bold')
    ax1.set_xlabel('电池健康度 (%)', fontsize=12)
    ax1.set_ylabel('频率', fontsize=12)
    ax1.grid(alpha=0.3)

    # 右图：按品牌的箱线图
    # 选择前8个品牌（按数量）
    top_brands = df['Make'].value_counts().head(8).index
    filtered_df = df[df['Make'].isin(top_brands)]

    boxplot = filtered_df.boxplot(column='Battery_Health_%', by='Make', ax=ax2)
    ax2.set_title('各品牌电池健康度分布', fontsize=14, fontweight='bold')
    ax2.set_xlabel('汽车品牌', fontsize=12)
    ax2.set_ylabel('电池健康度 (%)', fontsize=12)
    ax2.tick_params(axis='x', rotation=45)
    ax2.grid(alpha=0.3)

    plt.suptitle('电池健康度分析', fontsize=16, fontweight='bold')
    plt.tight_layout()

    return plot_to_base64(plt)


def plot_speed_vs_energy_consumption():
    """平均速度与能耗关系"""
    plt.figure(figsize=(12, 8))

    # 使用numpy计算相关系数
    correlation = np.corrcoef(df['Avg_Speed_kmh'], df['Energy_Consumption_kWh_per_100km'])[0, 1]

    # 按车辆类型分组
    vehicle_types = df['Vehicle_Type'].unique()
    colors = plt.cm.tab10(np.arange(len(vehicle_types)))

    # 创建散点图
    for i, vtype in enumerate(vehicle_types):
        subset = df[df['Vehicle_Type'] == vtype]
        plt.scatter(subset['Avg_Speed_kmh'], subset['Energy_Consumption_kWh_per_100km'],
                    color=colors[i], label=vtype, alpha=0.7, s=50)

    plt.title(f'平均速度与能耗关系 (相关系数: {correlation:.3f})', fontsize=16, fontweight='bold')
    plt.xlabel('平均速度 (km/h)', fontsize=12)
    plt.ylabel('能耗 (kWh/100km)', fontsize=12)
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
    plt.grid(alpha=0.3)

    return plot_to_base64(plt)


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)